﻿using UnityEngine;
using System.IO;
using System.Collections.Generic;

public class HexagnoalMap : Singleton<HexagnoalMap>
{
    public HashSet<Vector2Int> UnReachableHexCells; //用Vector2Int是因为x+y+z=0，所以不用保存z
    public int MaxCoor { get; private set; }
    [SerializeField]
    public HexagnoalMapData m_MapData;
    public float InnerRadius, OuterRadius;
    public GameObject hexCell;
    protected override void Awake()
    {
        base.Awake();
        //UnReachableHexCells = new HashSet<Vector2Int>(Vector2IntComparer.GetComperer());
        //gameObject.AddComponent<MeshFilter>().mesh = m_MapData.MapMesh;
        //gameObject.AddComponent<MeshRenderer>().sharedMaterial = m_MapData.MapMaterial;
        //gameObject.AddComponent<MeshCollider>().sharedMesh = m_MapData.MapMesh;
        //hexCell = new GameObject("Mouse");
        //hexCell.AddComponent<MeshFilter>().mesh = m_MapData.CellMesh;
        //hexCell.AddComponent<MeshRenderer>().sharedMaterial = m_MapData.CellMaterial;
       
    }
    //public void Start()
    //{
    //    Initialize(m_MapData.EdgeCount, m_MapData.OuterRadius);
    //}
    public void Initialize(int edgeCount, float outerRadius)
    {
        MaxCoor = edgeCount - 1;
        InnerRadius = outerRadius * 0.866025404f;
        this.OuterRadius = outerRadius;
        //byte[] buffs = m_MapData.UnReachableCells.bytes; //全是int类型
        //MemoryStream ms = new MemoryStream(buffs);
        //BinaryReader br = new BinaryReader(ms);
        //int cnt = br.ReadInt32();
        //Vector2Int coor;
        //while (cnt-- > 0)
        //{
        //    coor = new Vector2Int(br.ReadInt32(), br.ReadInt32());
        //    UnReachableHexCells.Add(coor);
        //    Transform tf = Instantiate(hexCell).transform;
        //    tf.position = GetPosition(coor);
        //    tf.parent = transform;
        //}
    }

    public Vector2Int GetCoor(Vector3 position)
    {
        //红为X，绿为Y，蓝为Z，由于该坐标系的特殊性，距离某一轴多少单位就是该轴分量的值
        //如距离X轴2单位，则X轴分量为2
        position = transform.InverseTransformPoint(position);
        float x = position.x / (InnerRadius * 2f);
        float y = -x;
        float offset = position.z / (OuterRadius * 3f);
        x -= offset;
        y -= offset;
        int ix = Mathf.RoundToInt(x);
        int iy = Mathf.RoundToInt(y);
        int iz = Mathf.RoundToInt(-x - y);
        if (ix + iy + iz != 0) //消除舍入误差
        {
            float dX = Mathf.Abs(x - ix);
            float dY = Mathf.Abs(y - iy);
            float dZ = Mathf.Abs(-x - y - iz);
            if (dX > dY && dX > dZ)
            {
                ix = -iy - iz;
            }
            else if (dY > dZ)
            {
                iy = -iz - ix;
            }
        }
        return new Vector2Int(ix, iy);
    }
    public Vector3 GetPosition(Vector2Int coor)
    {
        //在一个六边形单元格子中并不是所有点都可以用它的逆变换来求出在六边形坐标系上的坐标，因为在这种六边形坐标中班只有整点才满足x+y+z=0
        int z = -coor.x - coor.y;
        return transform.TransformPoint(new Vector3((coor.x - coor.y) * InnerRadius, 0f, z * OuterRadius * 1.5f));
    }
    /// <summary>
    /// 返回true，可到达点
    /// </summary>
    /// <param name="point"></param>
    /// <returns></returns>
    public bool IsReachablePoint(Vector2Int point)
    {
        return !UnReachableHexCells.Contains(point);
    }
    public Vector2Int? MousePointCell { get; private set; }
    private void Update()
    {
        RaycastHit hitInfo;
        if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hitInfo))
        {
            hexCell.SetActive(true);
            MousePointCell = GetCoor(hitInfo.point);
            hexCell.transform.position = GetPosition(MousePointCell.Value) + Vector3.up * 0.05f;
        }
        else
        {
            hexCell.SetActive(false);
            MousePointCell = null;
        }
    }
    public static int Distance(Vector2Int p1,Vector2Int p2)
    {
        //实际上地图上的两个点的距离是Mathf.Max(Mathf.Abs(x), Mathf.Max(Mathf.Abs(y), Mathf.Abs(z)))*innerRadius，但innerRadius可以在寻路过程中可以不用管
        int x = p1.x - p2.x, y = p1.y - p2.y;
        int z = -x - y;
        return Mathf.Max(Mathf.Abs(x), Mathf.Max(Mathf.Abs(y), Mathf.Abs(z)));
    }

}

